/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package ua.yandex.sumofseries.utilconcurrent;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class Sum {

    double sum(double n, int m) throws InterruptedException,
            ExecutionException {
        double temp = 2 * n / m;
        double k = -n;
        ExecutorService service = Executors.newFixedThreadPool(m);
        MyCallable[] r = new MyCallable[m];
        for (int i = 0; i < m; i++) {
            r[i] = new MyCallable(k, k + temp);
            service.submit(r[i]);
            k += temp;
        }
        double sum = 0;
        for (int i = 0; i < m; i++) {
            Future<Double> result = service.submit(r[i]);
            while (!result.isDone()) {
            }
            sum += result.get();
        }
        sum += Math.sin(n) * Math.cos(n);
        return sum;
    }

    public void dependenceTimeAndNumberOfThreads(double n)
            throws InterruptedException, ExecutionException {
        final int MAX = 50;
        for (int i = 1; i <= MAX; i++) {
            long timeout = System.currentTimeMillis();
            sum(n, i);
            System.out.print("AmountOfThreads =" + i);
            System.out.print("  Time = ");
            System.out.println(System.currentTimeMillis() - timeout);
        }
    }

    public class MyCallable implements Callable<Double> {

        private final double step = 0.0001;
        private final double end;
        private final double start;
        private double s;

        MyCallable(double st, double en) {
            start = st;
            end = en;
        }

        @Override
        public Double call() {
            for (double counter = start; counter < end; counter += step) {
                s += Math.sin(counter) * Math.cos(counter);
            }
            return s;
        }
    }
}
